/**
 * Copyright (c) 2018, 西安星沙网络科技-版权所有
 *
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.waleychain.exchange.service.impl.wallet.utils;

import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.azazar.bitcoin.jsonrpcclient.BitcoinAcceptor;

import cn.waleychain.exchange.service.impl.wallet.listener.EthReceiveListenerTwo;
import rx.Subscription;


public class WalletAcceptorUtil {

	public static final WalletAcceptorUtil instance = new WalletAcceptorUtil();
	private ConcurrentHashMap<Long, BitcoinAcceptor> acceptors = new ConcurrentHashMap<>();
	private ConcurrentHashMap<Long, ExecutorService> executors = new ConcurrentHashMap<>();
	private ConcurrentHashMap<Long, ScheduledExecutorService> ethAcceptor = new ConcurrentHashMap<>();
	private ConcurrentHashMap<Long, Subscription> ethTokenAcceptors = new ConcurrentHashMap<>();

	private WalletAcceptorUtil() {
	}

	public void upAcceptor(long coinId, BitcoinAcceptor acceptor) {
		if (this.acceptors.containsKey(coinId)) {
			this.delAcceptor(coinId);
		}

		ExecutorService exec = Executors.newSingleThreadExecutor();
		exec.execute(acceptor);
		this.acceptors.put(coinId, acceptor);
		this.executors.put(coinId, exec);
	}

	public void delAcceptor(long coinId) {
		if (this.acceptors.containsKey(coinId)) {
			BitcoinAcceptor old = (BitcoinAcceptor)this.acceptors.get(coinId);
			old.stopAccepting();
			this.acceptors.remove(coinId);
			ExecutorService oldexec = (ExecutorService)this.executors.get(coinId);
			oldexec.shutdown();
			this.executors.remove(coinId);
		}

	}

	public void upEthAcceptor(long coinId, EthReceiveListenerTwo listener) {
		if (this.ethAcceptor.contains(coinId)) {
			this.delEthAcceptor(coinId);
		}

		ScheduledExecutorService ethService = Executors.newSingleThreadScheduledExecutor();
		ethService.scheduleAtFixedRate(listener, 10000L, 60000L, TimeUnit.MILLISECONDS);
		this.ethAcceptor.put(coinId, ethService);
	}

	public void delEthAcceptor(long coinId) {
		if (this.ethAcceptor.containsKey(coinId)) {
			ScheduledExecutorService old = (ScheduledExecutorService)this.ethAcceptor.get(coinId);
			old.shutdownNow();
			this.ethAcceptor.remove(coinId);
		}

	}

	public void upEthTokenAcceptor(long coinId, Subscription subscription) {
		if (this.ethTokenAcceptors.containsKey(coinId)) {
			this.delEthTokenAcceptor(coinId);
		}

		this.ethTokenAcceptors.put(coinId, subscription);
	}

	public void delEthTokenAcceptor(long coinId) {
		if (this.ethTokenAcceptors.containsKey(coinId)) {
			Subscription subscription = (Subscription)this.ethTokenAcceptors.get(coinId);
			subscription.unsubscribe();
			this.ethTokenAcceptors.remove(coinId);
		}

	}

	public void cleanAll(long coinId) {
		this.delAcceptor(coinId);
		this.delEthAcceptor(coinId);
		this.delEthTokenAcceptor(coinId);
	}

	@SuppressWarnings("rawtypes")
	public void destoryAcceptor() {
		Enumeration keyEnum = this.executors.keys();

		while(keyEnum.hasMoreElements()) {
			ExecutorService exec = (ExecutorService)this.executors.get(keyEnum.nextElement());
			exec.shutdown();
		}

		Enumeration ethkeyEnum = this.ethAcceptor.keys();

		while(ethkeyEnum.hasMoreElements()) {
			this.delEthAcceptor(((Long)ethkeyEnum.nextElement()).longValue());
		}

		Enumeration ethTokenkeyEnum = this.ethTokenAcceptors.keys();

		while(ethTokenkeyEnum.hasMoreElements()) {
			this.delEthTokenAcceptor(((Long)ethTokenkeyEnum.nextElement()).longValue());
		}

	}
	
}
